package com.fr.base.core.antlr.preprocessor;

import com.fr.base.core.antlr.CodeGenerator;
import com.fr.base.core.antlr.Tool;
import com.fr.base.core.antlr.collections.impl.IndexedVector;
import java.io.IOException;
import java.util.Enumeration;

class Grammar
{
  protected String name;
  protected String fileName;
  protected String superGrammar;
  protected String type;
  protected IndexedVector rules;
  protected IndexedVector options;
  protected String tokenSection;
  protected String preambleAction;
  protected String memberAction;
  protected Hierarchy hier;
  protected boolean predefined = false;
  protected boolean alreadyExpanded = false;
  protected boolean specifiedVocabulary = false;
  protected String superClass = null;
  protected String importVocab = null;
  protected String exportVocab = null;
  protected Tool antlrTool;

  public Grammar(Tool paramTool, String paramString1, String paramString2, IndexedVector paramIndexedVector)
  {
    this.name = paramString1;
    this.superGrammar = paramString2;
    this.rules = paramIndexedVector;
    this.antlrTool = paramTool;
  }

  public void addOption(Option paramOption)
  {
    if (this.options == null)
      this.options = new IndexedVector();
    this.options.appendElement(paramOption.getName(), paramOption);
  }

  public void addRule(Rule paramRule)
  {
    this.rules.appendElement(paramRule.getName(), paramRule);
  }

  public void expandInPlace()
  {
    Object localObject2;
    Object localObject3;
    if (this.alreadyExpanded)
      return;
    Grammar localGrammar = getSuperGrammar();
    if (localGrammar == null)
      return;
    if (this.exportVocab == null)
      this.exportVocab = getName();
    if (localGrammar.isPredefined())
      return;
    localGrammar.expandInPlace();
    this.alreadyExpanded = true;
    GrammarFile localGrammarFile = this.hier.getFile(getFileName());
    localGrammarFile.setExpanded(true);
    IndexedVector localIndexedVector = localGrammar.getRules();
    Object localObject1 = localIndexedVector.elements();
    while (((Enumeration)localObject1).hasMoreElements())
    {
      localObject2 = (Rule)((Enumeration)localObject1).nextElement();
      inherit((Rule)localObject2, localGrammar);
    }
    localObject1 = localGrammar.getOptions();
    if (localObject1 != null)
    {
      localObject2 = ((IndexedVector)localObject1).elements();
      while (((Enumeration)localObject2).hasMoreElements())
      {
        localObject3 = (Option)((Enumeration)localObject2).nextElement();
        inherit((Option)localObject3, localGrammar);
      }
    }
    if (((this.options != null) && (this.options.getElement("importVocab") == null)) || (this.options == null))
    {
      localObject2 = new Option("importVocab", localGrammar.exportVocab + ";", this);
      addOption((Option)localObject2);
      localObject3 = localGrammar.getFileName();
      String str1 = this.antlrTool.pathToFile((String)localObject3);
      String str2 = str1 + localGrammar.exportVocab + CodeGenerator.TokenTypesFileSuffix + CodeGenerator.TokenTypesFileExt;
      String str3 = this.antlrTool.fileMinusPath(str2);
      if (str1.equals("." + System.getProperty("file.separator")))
        break label368:
      try
      {
        this.antlrTool.copyFile(str2, str3);
      }
      catch (IOException localIOException)
      {
        this.antlrTool.toolError("cannot find/copy importVocab file " + str2);
        return;
      }
    }
    label368: inherit(localGrammar.memberAction, localGrammar);
  }

  public String getFileName()
  {
    return this.fileName;
  }

  public String getName()
  {
    return this.name;
  }

  public IndexedVector getOptions()
  {
    return this.options;
  }

  public IndexedVector getRules()
  {
    return this.rules;
  }

  public Grammar getSuperGrammar()
  {
    if (this.superGrammar == null)
      return null;
    Grammar localGrammar = this.hier.getGrammar(this.superGrammar);
    return localGrammar;
  }

  public String getSuperGrammarName()
  {
    return this.superGrammar;
  }

  public String getType()
  {
    return this.type;
  }

  public void inherit(Option paramOption, Grammar paramGrammar)
  {
    if ((paramOption.getName().equals("importVocab")) || (paramOption.getName().equals("exportVocab")))
      return;
    Option localOption = null;
    if (this.options != null)
      localOption = (Option)this.options.getElement(paramOption.getName());
    if (localOption == null)
      addOption(paramOption);
  }

  public void inherit(Rule paramRule, Grammar paramGrammar)
  {
    Rule localRule = (Rule)this.rules.getElement(paramRule.getName());
    if (localRule != null)
      if (!(localRule.sameSignature(paramRule)))
        this.antlrTool.warning("rule " + getName() + "." + localRule.getName() + " has different signature than " + paramGrammar.getName() + "." + localRule.getName());
    else
      addRule(paramRule);
  }

  public void inherit(String paramString, Grammar paramGrammar)
  {
    if (this.memberAction != null)
      return;
    if (paramString != null)
      this.memberAction = paramString;
  }

  public boolean isPredefined()
  {
    return this.predefined;
  }

  public void setFileName(String paramString)
  {
    this.fileName = paramString;
  }

  public void setHierarchy(Hierarchy paramHierarchy)
  {
    this.hier = paramHierarchy;
  }

  public void setMemberAction(String paramString)
  {
    this.memberAction = paramString;
  }

  public void setOptions(IndexedVector paramIndexedVector)
  {
    this.options = paramIndexedVector;
  }

  public void setPreambleAction(String paramString)
  {
    this.preambleAction = paramString;
  }

  public void setPredefined(boolean paramBoolean)
  {
    this.predefined = paramBoolean;
  }

  public void setTokenSection(String paramString)
  {
    this.tokenSection = paramString;
  }

  public void setType(String paramString)
  {
    this.type = paramString;
  }

  public String toString()
  {
    StringBuffer localStringBuffer = new StringBuffer(10000);
    if (this.preambleAction != null)
      localStringBuffer.append(this.preambleAction);
    if (this.superGrammar == null)
      return "class " + this.name + ";";
    if (this.superClass != null)
      localStringBuffer.append("class " + this.name + " extends " + this.superClass + ";");
    else
      localStringBuffer.append("class " + this.name + " extends " + this.type + ";");
    localStringBuffer.append(System.getProperty("line.separator") + System.getProperty("line.separator"));
    if (this.options != null)
      localStringBuffer.append(Hierarchy.optionsToString(this.options));
    if (this.tokenSection != null)
      localStringBuffer.append(this.tokenSection + "\n");
    if (this.memberAction != null)
      localStringBuffer.append(this.memberAction + System.getProperty("line.separator"));
    for (int i = 0; i < this.rules.size(); ++i)
    {
      Rule localRule = (Rule)this.rules.elementAt(i);
      if (!(getName().equals(localRule.enclosingGrammar.getName())))
        localStringBuffer.append("// inherited from grammar " + localRule.enclosingGrammar.getName() + System.getProperty("line.separator"));
      localStringBuffer.append(localRule + System.getProperty("line.separator") + System.getProperty("line.separator"));
    }
    return localStringBuffer.toString();
  }
}